import * as fsExtra from 'fs-extra';
import * as path from 'path';
import { omit } from 'lodash/fp';
import autoprefixer from 'autoprefixer';
import typescript from 'rollup-plugin-typescript2';
import json from 'rollup-plugin-json';
import commonjs from 'rollup-plugin-commonjs';
import nodeResolve from 'rollup-plugin-node-resolve';
import alias from 'rollup-plugin-alias';
import postcss from 'rollup-plugin-postcss';
import progress from 'rollup-plugin-progress';
import clean from 'docz-rollup/src/plugins/clean';
import size from 'docz-rollup/src/plugins/size';
import sass from 'node-sass';

const cwd = process.cwd();
const pkgDir = path.join(cwd, 'packages');
const filter = process.env.BUILD_PKG
    ? process.env.BUILD_PKG.split(',').map(str => str.trim())
    : null;

function packageFilter(dir) {
    return filter ? filter.indexOf(dir) !== -1 : dir;
}

function sortByExternal({ pkg: p1 }, { pkg: p2 }) {
    const deps1 = { ...p1.dependencies, ...p1.devDependencies, ...p1.peerDependencies };
    const deps2 = { ...p2.dependencies, ...p2.devDependencies, ...p2.peerDependencies };
    if (deps1[p2.name]) return 1;
    if (deps2[p1.name]) return -1;
    return p1.name > p2.name ? -1 : p1.name < p2.name ? 1 : 0;
}

const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.es6', '.es', '.mjs'];
const omitOpts = omit(['alias', 'external', 'output', 'plugins', 'runtimeHelpers', 'filename']);
const processSass = function(context, payload) {
    return new Promise((resolve, reject) => {
        sass.render(
            {
                file: context
            },
            function(err, result) {
                if (!err) {
                    resolve(result);
                } else {
                    reject(err);
                }
            }
        );
    });
};

const defaultExternal = id =>
    !id.startsWith('\0') &&
    !id.startsWith('~') &&
    !id.startsWith('.') &&
    !id.startsWith(process.platform === 'win32' ? process.cwd() : '/');

const createOutput = (dir = 'dist', defaultOpts) => {
    const opts = omitOpts(defaultOpts);
    const { alias: moduleAlias, external, plugins = [], filename } = defaultOpts;
    const defaultPlugins = [
        clean(dir),
        postcss({
            extract: true,
            minimize: true,
            plugins: [autoprefixer()],
            extensions: ['css', 'scss'],
            process: processSass
        }),
        Object.keys(moduleAlias || {}).length > 0 &&
            alias({
                ...moduleAlias,
                resolve: EXTENSIONS
            }),
        nodeResolve({
            mainFields: ['module', 'main'],
            browser: true
        }),
        commonjs({ include: /\/node_modules\// }),
        json(),
        size(dir),
        progress({ clearLine: false })
    ];
    const output = [
        {
            dir,
            format: 'cjs',
            chunkFileNames: filename ? `${filename}.js` : `[name].js`,
            entryFileNames: filename ? `${filename}.js` : `[name].js`
        },
        {
            dir,
            format: 'esm',
            chunkFileNames: filename ? `${filename}.esm.js` : `[name].esm.js`,
            entryFileNames: filename ? `${filename}.esm.js` : `[name].esm.js`
        }
    ];

    return {
        ...opts,
        external: external || defaultExternal,
        plugins: defaultPlugins.filter(Boolean).concat(plugins),
        output
    };
};

export default fsExtra
    .readdir(pkgDir)
    .then(dirs =>
        Promise.all(
            dirs.filter(packageFilter).map(dir =>
                fsExtra.readJson(path.join(pkgDir, dir, 'package.json')).then(pkg => ({
                    pkg,
                    pkgDir: path.join(pkgDir, dir),
                    srcDir: path.join(pkgDir, dir, 'src')
                }))
            )
        )
    )
    .then(recs =>
        recs.sort(sortByExternal).map(({ pkg, pkgDir, srcDir }) => {
            const conf = createOutput(`packages/${pkg.name}/dist`, {
                runtimeHelpers: true,
                moduleAlias: {
                    entries: [
                        {
                            find: 'comuse-theme',
                            replacement: path.resolve(pkgDir, '../comuse-theme')
                        },
                        {
                            find: 'comuse-ui',
                            replacement: path.resolve(pkgDir, '../comuse-ui')
                        }
                    ]
                },
                input: path.join(srcDir, 'index.ts'),
                plugins: [
                    typescript({
                        abortOnError: true,
                        check: true,
                        exclude: ['*.spec*', '**/*.spec*'],
                        tsconfig: path.join(__dirname, 'tsconfig.json'),
                        tsconfigOverride: {
                            compilerOptions: {
                                paths: null,
                                rootDir: srcDir
                            },
                            include: [srcDir]
                        }
                    })
                ]
            });
            return conf;
        })
    );
